05 Resolvers

Próxima Atividade
  • Sugerir melhoria
Play
Current Time 0:00
/
Duration Time 0:00
Remaining Time -0:00
Stream TypeLIVE
Loaded: 0%
Progress: 0%
0:00
Fullscreen
00:00
Mute
Playback Rate
  • 2x
  • 1.5x
  • 1.2x
  • 1x
  • 0.8x
  • 0.7x
1x
Subtitles
  • subtitles off
Captions
  • captions off
Chapters
  • Chapters
HD
Desculpe-nos pelo transtorno, mas este video não pode ser carregado, tente novamente.

Transcrição

Nosso filtro está funcionando como gostaríamos, porém há um detalhe a respeito da última mensagem que implementamos, "Sorry, no photos", que apenas alguém mais atento conseguirá notar. Ao recarregarmos a página, a mensagem é exibida durante alguns poucos segundos, antes da listagem ser carregada. Isso é meio estranho, não?

Não fizemos uma requisição à API para que os dados das imagens fossem trazidos? Sendo assim, esta mensagem deveria aparecer somente em decorrência do filtro. Isso pode acabar deixando o usuário frustrado, ainda mais se for uma operação que acabar demorando.

Em photo-list.component.ts, a lista de imagens começa com um array vazia (photos: Photo[] = []), então, quando o componente é carregado, a lista será considerada no *ngIf e a mensagem será exibida. Depois, na inicialização ngOnInit(), os dados serão trazidos da API e colocados na propriedade photos, que então terá dados, fazendo com que a mensagem deixe de ser exibida.

O problema é que a busca destes dados está sendo feita no componente, então, para que a mensagem não apareça, o ideal é que o componente receba a lista de imagens pronta antes de navegarmos a ele. Em suma, entraremos na rota e, antes do componente ser criado e renderizado, resolveremos e disponibilizaremos os dados de que ele precisa. Deste modo, o componente receberá os dados prontos, sem precisar buscá-los, e o array de imagens será preenchido.

Podemos resolver este tipo de problema com o Angular, por meio do Resolver, capaz de lidar com dados durante a navegação de uma rota para disponibilizá-los a um componente antes deste ser carregado.

Por estar muito atrelado ao "photo-list", criaremos nosso arquivo nesta pasta, e o chamaremos de photo-list.resolver.ts. Precisamos do serviço PhotoService no construtor desta classe para resolvermos esta dependência. E sabemos que, para ser injetável, termos acesso ao PhotoService e podermos utilizar o Resolver, teremos um @Injectable().

Para ser um Resolver, a classe precisará implementar a interface Resolve, genérica, e que devolverá o tipo de dado retornado pelo listFromUser(), um Observable<Photo[]>. Ambos precisarão ser importados. Para conseguirmos trabalhar com o PhotoListResolver, implementaremos o método resolve(), e o Visual Studio está se recusando a adicioná-lo automaticamente, mas não tem problema, faremos isto manualmente.

Como parâmetro, este método receberá ActivatedRouteSnapshot, que tirará um screenshot do que estiver acontecendo no momento, e um state, RouterStateSnapshot. Teremos uma variável const userName, cujo resultado será route.params.userName. Depois, usaremos o return com this.service.listFromUser().

import { Injectable } from '@angular/core';
import { Resolve } from '@angular/router';
import { Observable } from 'rxjs';

import { PhotoService } from '../photo/photo.service';
import { Photo } from '../photo/photo';

@Injectable({ providedIn: 'root'})
export class PhotoListResolver implements Resolve<Observable<Photo[]>>{

    constructor(private service: PhotoService) {}

    resolve(route: ActivatedRouteSnapshot, state: RouterStateSnapshot) {
        const userName = route.params.userName;
        return this.service.listFromUser(userName);
    }

}

Assim, se passarmos o mouse sobre resolve(), será indicado que o retorno é do tipo Observable<Photo[]>, o que também pode ser explicitado usando-se dois pontos:

resolve(route: ActivatedRouteSnapshot, state: RouterStateSnapshot): Observable<Photo[]> {
  const userName = route.params.userName;
  return this.service.listFromUser(userName);
}

Entretanto, ainda precisaremos acessar o arquivo de rotas, app.routing.module.ts. Como o Resolver é acionado no momento em que a rota está sendo resolvida, é ali que se encontra sua configuração. Portanto, incluiremos resolve passando um objeto JavaScript para disponibilizar a propriedade photos com o resultado de PhotoListResolver:

path: 'user/:userName',
component: PhotoListComponent,
resolve: {
    photos: PhotoListResolver
}

E em photo-list.component.ts, deletaremos o seguinte trecho, que passa a ser desnecessário:

const userName = this.activatedRoute
    .snapshot
    .params
    .userName;

this.photoService
    .listFromUser(userName)
    .subscribe(photos => this.photos = photos);

Em consequência, removeremos também private photoService: PhotoService em constructor(), e o seu respectivo importe. Em ngOnInit(), incluiremos this.photos = this.activatedRoute.snapshot.data.photos, cujo snapshot.data nos permite acessar o valor contido em photos de app.routing.module.ts.

Também é possível usar this.activatedRoute.snapshot.data['photos'].

Com isso indicamos que é preciso buscar dados em photos, nome da propriedade usada no Routes, para esta rota que foi ativada. Salvaremos tudo, voltaremos ao navegador e acessaremos localhost:4200/user/flavio. As imagens são buscadas, e então recarregaremos a página e, em nenhum momento, a mensagem "Sorry, no photos" é exibida, pois os dados são resolvidos no sistema de rotas.

Esta é a motivação por trás do Resolver — a resolução de dados assíncronos dos quais o componente depende antes de ser ativado, no momento em que ativamos a rota, antes mesmo dela avaliar tal componente.

Tirar dúvida Próxima Atividade
ícone Angular parte 1: Fundamentos

Angular parte 1: Fundamentos

100%
Aula06 de 07

Melhorando a experiência do usuário

Atividades 5 de 11

  • 01 Projeto da aula anterior
  • 02 Binding de eventos 11min
  • 03 Pipe e implementação 14min
  • 04 Criando nosso próprio pipe
  • 05 Resolvers 12min
  • 06 Implementando Resolvers
  • 07 RxJS e seu Subject 12min
  • 08 Padrão debounce com RxJS
  • 09 Paginação de dados 07min
  • 10 LoadButton 16min
  • 11 Consolidando seu conhecimento

Aulas

Outros Links

Fórum Trocar Curso
Gravatar de Marcos Katsumi Kay

Marcos Katsumi Kay 34.4k xp

Logo da Alura